/*
 * XML Schema Editor
 * This code may be freely modified and distributed.
 * 
 * History:
 * 
 * Version 1.0
 *	First release, Marc Clifton
*/
/*
 * Version 1.0
 * 
 * Quirks:
 *	1. Clicking on node A while in the middle of editing node B results in the name being changed for node A (mouse down event handler sets the current node!)
 *	2. After editing the schema in the text edit box, you MUST compile otherwise changes will be lost!
 *	3. If the tree node doesn't match the schema object, there are blank lines in the XSD file which are causing synchronization problems.  Select "Schema/Compile" from menu.
 * 
 * Bugs:
 *   1. Editing the name of a complex type adds a "name" to the CT, not the parent element
 * 
 * Features:
 *	dynamically adjusts for global and local types
 *	dynamically creates complex types from elements
 *	selecting a tree node highlights the corresponding XML text
 *	compiler error window
 *	xml can be edited directly instead of using the tree
 *	creates and manages global types list as types are added and removed
 *	keyboard shortcuts:
 *		F2-edit node label
 *		Ctrl-A : add to schema at current node
 *		Ctrl-T : go to top of schema
 *		Ctrl-P : got to parent of current node
 * 
 * Notes:
 * 
 * Need to do:
 * 
 * Missing features:
 *	Auto-scroll edit box to show selected node
 *	Remember selected node when compiling schema
 *	Implement XmlSchemaElement minOccurs and maxOccurs with GUI to enter values
 *	Implement XmlSchemaAttribute fixed and use with GUI to enter values
 *	Implement XmlSchemaGroup
 *	...others?
 * 
 */

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;

namespace xmlSchemaEditor
{
	public class SchemaEditor : System.Windows.Forms.Form
	{
		#region data
		private System.Windows.Forms.TreeView tvSchema;
		private System.Windows.Forms.ContextMenu tvcmSchema;
		private System.Windows.Forms.MenuItem mnuAddElement;
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.TextBox edSchema;
		private System.Windows.Forms.MenuItem mnuAddSimpleType;
		private System.Windows.Forms.MenuItem mnuAddComplexType;
		private System.Windows.Forms.MainMenu mainMenu;
		private System.Windows.Forms.MenuItem mnuFile;
		private System.Windows.Forms.MenuItem mnuNew;
		private System.Windows.Forms.MenuItem mnuOpen;
		private System.Windows.Forms.MenuItem mnuSave;
		private System.Windows.Forms.MenuItem mnuSaveAs;
		private System.Windows.Forms.MenuItem mnuExit;
		private System.Windows.Forms.MenuItem menuItem2;
		private System.Windows.Forms.MenuItem menuItem3;
		private System.Windows.Forms.MenuItem mnuAbout;
		private System.Windows.Forms.OpenFileDialog openSchemaDialog;
		private System.Windows.Forms.ImageList tvImageList;
		private System.Windows.Forms.MenuItem mnuAddAnnotation;
		private System.Windows.Forms.MenuItem mnuAddAttribute;
		private System.Windows.Forms.TextBox edSchemaErrors;
		private System.Windows.Forms.MenuItem menuItem1;
		private System.Windows.Forms.MenuItem mnuCompile;
		private System.Windows.Forms.GroupBox gbSelectType;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.MenuItem menuItem4;
		private System.Windows.Forms.MenuItem mnuRemoveNode;
		private System.Windows.Forms.MenuItem menuItem6;
		private System.Windows.Forms.MenuItem menuItem7;
		private System.Windows.Forms.MenuItem menuItem5;
		private System.Windows.Forms.MenuItem menuItem9;
		private System.Windows.Forms.ComboBox cbGlobalTypes;
		private System.Windows.Forms.ComboBox cbSimpleTypes;
		private XmlSchema schema;
		private System.Windows.Forms.MenuItem mnuFacetEnumeration;
		private System.Windows.Forms.MenuItem mnuFacetMaxExclusive;
		private System.Windows.Forms.MenuItem mnuFacetMaxInclusive;
		private System.Windows.Forms.MenuItem mnuFacetMinExclusive;
		private System.Windows.Forms.MenuItem mnuFacetMinInclusive;
		private System.Windows.Forms.MenuItem mnuFacetNumeric;
		private System.Windows.Forms.MenuItem mnuFacetPattern;
		private System.Windows.Forms.MenuItem mnuFacetWhiteSpace;
		private System.Windows.Forms.MenuItem mnuFacetFractionDigits;
		private System.Windows.Forms.MenuItem mnuFacetLength;
		private System.Windows.Forms.MenuItem mnuFacetMaxLength;
		private System.Windows.Forms.MenuItem mnuFacetMinLength;
		private System.Windows.Forms.MenuItem mnuFacetTotalDigits;
		private System.Windows.Forms.MenuItem mnuAddDocumentation;
		private System.Windows.Forms.MenuItem mnuAddAppInfo;
		private string prevLabel;
		private System.Windows.Forms.SaveFileDialog saveAsSchemaDialog;
		private string fileName=null;
		enum TreeViewImages {Schema, Element, SimpleType, ComplexType, Annotation, Documentation, AppInfo, Attribute, Facet};
		#endregion

		#region GlobalElementType
		public class GlobalElementType
		{
			public GlobalElementType(string name, XmlSchemaObject type)
			{
				this.name=name;
				this.type=type;
			}

			public override string ToString()
			{
				return name;
			}

			public string Get()
			{
				return name;
			}

			public void Set(string name)
			{
				this.name=name;
			}

			public string name;
			public XmlSchemaObject type;
		}
		#endregion

		#region SchemaEditor Class
		public SchemaEditor()
		{
			InitializeComponent();
			CreateRootNode();
			tvSchema.LabelEdit=true;
			tvSchema.KeyUp+=new KeyEventHandler(EventTreeViewKeyUp);
			tvSchema.BeforeLabelEdit+=new NodeLabelEditEventHandler(PreEventLabelChanged);
			tvSchema.AfterLabelEdit+=new NodeLabelEditEventHandler(EventLabelChanged);
			tvSchema.MouseDown+=new MouseEventHandler(EventMouseDown);
			edSchema.LostFocus+=new EventHandler(EventSchemaTextBoxLostFocus);
			schema=new XmlSchema();
			CompileSchema();
		}

		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		static void Main() 
		{
			Application.Run(new SchemaEditor());
		}

		#endregion

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SchemaEditor));
            this.tvSchema = new System.Windows.Forms.TreeView();
            this.tvcmSchema = new System.Windows.Forms.ContextMenu();
            this.mnuAddElement = new System.Windows.Forms.MenuItem();
            this.mnuAddSimpleType = new System.Windows.Forms.MenuItem();
            this.mnuAddComplexType = new System.Windows.Forms.MenuItem();
            this.mnuAddAttribute = new System.Windows.Forms.MenuItem();
            this.menuItem9 = new System.Windows.Forms.MenuItem();
            this.menuItem5 = new System.Windows.Forms.MenuItem();
            this.mnuAddAnnotation = new System.Windows.Forms.MenuItem();
            this.mnuAddDocumentation = new System.Windows.Forms.MenuItem();
            this.mnuAddAppInfo = new System.Windows.Forms.MenuItem();
            this.menuItem4 = new System.Windows.Forms.MenuItem();
            this.menuItem7 = new System.Windows.Forms.MenuItem();
            this.mnuFacetEnumeration = new System.Windows.Forms.MenuItem();
            this.mnuFacetMaxExclusive = new System.Windows.Forms.MenuItem();
            this.mnuFacetMaxInclusive = new System.Windows.Forms.MenuItem();
            this.mnuFacetMinExclusive = new System.Windows.Forms.MenuItem();
            this.mnuFacetMinInclusive = new System.Windows.Forms.MenuItem();
            this.mnuFacetNumeric = new System.Windows.Forms.MenuItem();
            this.mnuFacetFractionDigits = new System.Windows.Forms.MenuItem();
            this.mnuFacetLength = new System.Windows.Forms.MenuItem();
            this.mnuFacetMaxLength = new System.Windows.Forms.MenuItem();
            this.mnuFacetMinLength = new System.Windows.Forms.MenuItem();
            this.mnuFacetTotalDigits = new System.Windows.Forms.MenuItem();
            this.mnuFacetPattern = new System.Windows.Forms.MenuItem();
            this.mnuFacetWhiteSpace = new System.Windows.Forms.MenuItem();
            this.menuItem6 = new System.Windows.Forms.MenuItem();
            this.mnuRemoveNode = new System.Windows.Forms.MenuItem();
            this.tvImageList = new System.Windows.Forms.ImageList(this.components);
            this.edSchema = new System.Windows.Forms.TextBox();
            this.mainMenu = new System.Windows.Forms.MainMenu(this.components);
            this.mnuFile = new System.Windows.Forms.MenuItem();
            this.mnuNew = new System.Windows.Forms.MenuItem();
            this.mnuOpen = new System.Windows.Forms.MenuItem();
            this.menuItem3 = new System.Windows.Forms.MenuItem();
            this.mnuSave = new System.Windows.Forms.MenuItem();
            this.mnuSaveAs = new System.Windows.Forms.MenuItem();
            this.menuItem2 = new System.Windows.Forms.MenuItem();
            this.mnuExit = new System.Windows.Forms.MenuItem();
            this.menuItem1 = new System.Windows.Forms.MenuItem();
            this.mnuCompile = new System.Windows.Forms.MenuItem();
            this.mnuAbout = new System.Windows.Forms.MenuItem();
            this.openSchemaDialog = new System.Windows.Forms.OpenFileDialog();
            this.edSchemaErrors = new System.Windows.Forms.TextBox();
            this.gbSelectType = new System.Windows.Forms.GroupBox();
            this.cbGlobalTypes = new System.Windows.Forms.ComboBox();
            this.cbSimpleTypes = new System.Windows.Forms.ComboBox();
            this.label2 = new System.Windows.Forms.Label();
            this.label1 = new System.Windows.Forms.Label();
            this.saveAsSchemaDialog = new System.Windows.Forms.SaveFileDialog();
            this.gbSelectType.SuspendLayout();
            this.SuspendLayout();
            // 
            // tvSchema
            // 
            this.tvSchema.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)));
            this.tvSchema.ContextMenu = this.tvcmSchema;
            this.tvSchema.FullRowSelect = true;
            this.tvSchema.HideSelection = false;
            this.tvSchema.ImageIndex = 0;
            this.tvSchema.ImageList = this.tvImageList;
            this.tvSchema.Location = new System.Drawing.Point(8, 8);
            this.tvSchema.Name = "tvSchema";
            this.tvSchema.SelectedImageIndex = 0;
            this.tvSchema.Size = new System.Drawing.Size(280, 517);
            this.tvSchema.TabIndex = 0;
            this.tvSchema.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.tvSchema_AfterSelect);
            // 
            // tvcmSchema
            // 
            this.tvcmSchema.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuAddElement,
            this.mnuAddSimpleType,
            this.mnuAddComplexType,
            this.mnuAddAttribute,
            this.menuItem9,
            this.menuItem5,
            this.menuItem4,
            this.menuItem7,
            this.menuItem6,
            this.mnuRemoveNode});
            // 
            // mnuAddElement
            // 
            this.mnuAddElement.Index = 0;
            this.mnuAddElement.Text = "Element";
            this.mnuAddElement.Click += new System.EventHandler(this.mnuAddElement_Click);
            // 
            // mnuAddSimpleType
            // 
            this.mnuAddSimpleType.Index = 1;
            this.mnuAddSimpleType.Text = "Simple Type";
            this.mnuAddSimpleType.Click += new System.EventHandler(this.mnuAddSimpleType_Click);
            // 
            // mnuAddComplexType
            // 
            this.mnuAddComplexType.Index = 2;
            this.mnuAddComplexType.Text = "Complex Type";
            this.mnuAddComplexType.Click += new System.EventHandler(this.mnuAddComplexType_Click);
            // 
            // mnuAddAttribute
            // 
            this.mnuAddAttribute.Index = 3;
            this.mnuAddAttribute.Text = "Attribute";
            this.mnuAddAttribute.Click += new System.EventHandler(this.mnuAddAttribute_Click);
            // 
            // menuItem9
            // 
            this.menuItem9.Index = 4;
            this.menuItem9.Text = "-";
            // 
            // menuItem5
            // 
            this.menuItem5.Index = 5;
            this.menuItem5.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuAddAnnotation,
            this.mnuAddDocumentation,
            this.mnuAddAppInfo});
            this.menuItem5.Text = "Annotation";
            // 
            // mnuAddAnnotation
            // 
            this.mnuAddAnnotation.Index = 0;
            this.mnuAddAnnotation.Text = "Annotation";
            this.mnuAddAnnotation.Click += new System.EventHandler(this.mnuAddAnnotation_Click);
            // 
            // mnuAddDocumentation
            // 
            this.mnuAddDocumentation.Index = 1;
            this.mnuAddDocumentation.Text = "Documentation";
            this.mnuAddDocumentation.Click += new System.EventHandler(this.mnuAddDocumentation_Click);
            // 
            // mnuAddAppInfo
            // 
            this.mnuAddAppInfo.Index = 2;
            this.mnuAddAppInfo.Text = "App Info";
            this.mnuAddAppInfo.Click += new System.EventHandler(this.mnuAddAppInfo_Click);
            // 
            // menuItem4
            // 
            this.menuItem4.Index = 6;
            this.menuItem4.Text = "-";
            // 
            // menuItem7
            // 
            this.menuItem7.Index = 7;
            this.menuItem7.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuFacetEnumeration,
            this.mnuFacetMaxExclusive,
            this.mnuFacetMaxInclusive,
            this.mnuFacetMinExclusive,
            this.mnuFacetMinInclusive,
            this.mnuFacetNumeric,
            this.mnuFacetPattern,
            this.mnuFacetWhiteSpace});
            this.menuItem7.Text = "Facet";
            // 
            // mnuFacetEnumeration
            // 
            this.mnuFacetEnumeration.Index = 0;
            this.mnuFacetEnumeration.Text = "Enumeration";
            this.mnuFacetEnumeration.Click += new System.EventHandler(this.mnuFacetEnumeration_Click);
            // 
            // mnuFacetMaxExclusive
            // 
            this.mnuFacetMaxExclusive.Index = 1;
            this.mnuFacetMaxExclusive.Text = "Max Exclusive";
            this.mnuFacetMaxExclusive.Click += new System.EventHandler(this.mnuFacetMaxExclusive_Click);
            // 
            // mnuFacetMaxInclusive
            // 
            this.mnuFacetMaxInclusive.Index = 2;
            this.mnuFacetMaxInclusive.Text = "Max Inclusive";
            this.mnuFacetMaxInclusive.Click += new System.EventHandler(this.mnuFacetMaxInclusive_Click);
            // 
            // mnuFacetMinExclusive
            // 
            this.mnuFacetMinExclusive.Index = 3;
            this.mnuFacetMinExclusive.Text = "Min Exclusive";
            this.mnuFacetMinExclusive.Click += new System.EventHandler(this.mnuFacetMinExclusive_Click);
            // 
            // mnuFacetMinInclusive
            // 
            this.mnuFacetMinInclusive.Index = 4;
            this.mnuFacetMinInclusive.Text = "Min Inclusive";
            this.mnuFacetMinInclusive.Click += new System.EventHandler(this.mnuFacetMinInclusive_Click);
            // 
            // mnuFacetNumeric
            // 
            this.mnuFacetNumeric.Index = 5;
            this.mnuFacetNumeric.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuFacetFractionDigits,
            this.mnuFacetLength,
            this.mnuFacetMaxLength,
            this.mnuFacetMinLength,
            this.mnuFacetTotalDigits});
            this.mnuFacetNumeric.Text = "Numeric";
            // 
            // mnuFacetFractionDigits
            // 
            this.mnuFacetFractionDigits.Index = 0;
            this.mnuFacetFractionDigits.Text = "Fraction Digits";
            this.mnuFacetFractionDigits.Click += new System.EventHandler(this.mnuFacetFractionDigits_Click);
            // 
            // mnuFacetLength
            // 
            this.mnuFacetLength.Index = 1;
            this.mnuFacetLength.Text = "Length";
            this.mnuFacetLength.Click += new System.EventHandler(this.mnuFacetLength_Click);
            // 
            // mnuFacetMaxLength
            // 
            this.mnuFacetMaxLength.Index = 2;
            this.mnuFacetMaxLength.Text = "Max Length";
            this.mnuFacetMaxLength.Click += new System.EventHandler(this.mnuFacetMaxLength_Click);
            // 
            // mnuFacetMinLength
            // 
            this.mnuFacetMinLength.Index = 3;
            this.mnuFacetMinLength.Text = "Min Length";
            this.mnuFacetMinLength.Click += new System.EventHandler(this.mnuFacetMinLength_Click);
            // 
            // mnuFacetTotalDigits
            // 
            this.mnuFacetTotalDigits.Index = 4;
            this.mnuFacetTotalDigits.Text = "Total Digits";
            this.mnuFacetTotalDigits.Click += new System.EventHandler(this.mnuFacetTotalDigits_Click);
            // 
            // mnuFacetPattern
            // 
            this.mnuFacetPattern.Index = 6;
            this.mnuFacetPattern.Text = "Pattern";
            this.mnuFacetPattern.Click += new System.EventHandler(this.mnuFacetPattern_Click);
            // 
            // mnuFacetWhiteSpace
            // 
            this.mnuFacetWhiteSpace.Index = 7;
            this.mnuFacetWhiteSpace.Text = "White Space";
            this.mnuFacetWhiteSpace.Click += new System.EventHandler(this.mnuFacetWhiteSpace_Click);
            // 
            // menuItem6
            // 
            this.menuItem6.Index = 8;
            this.menuItem6.Text = "-";
            // 
            // mnuRemoveNode
            // 
            this.mnuRemoveNode.Index = 9;
            this.mnuRemoveNode.Text = "Remove";
            this.mnuRemoveNode.Click += new System.EventHandler(this.mnuRemoveNode_Click);
            // 
            // tvImageList
            // 
            this.tvImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("tvImageList.ImageStream")));
            this.tvImageList.TransparentColor = System.Drawing.Color.Transparent;
            this.tvImageList.Images.SetKeyName(0, "");
            this.tvImageList.Images.SetKeyName(1, "");
            this.tvImageList.Images.SetKeyName(2, "");
            this.tvImageList.Images.SetKeyName(3, "");
            this.tvImageList.Images.SetKeyName(4, "");
            this.tvImageList.Images.SetKeyName(5, "");
            this.tvImageList.Images.SetKeyName(6, "");
            this.tvImageList.Images.SetKeyName(7, "");
            this.tvImageList.Images.SetKeyName(8, "");
            // 
            // edSchema
            // 
            this.edSchema.AcceptsReturn = true;
            this.edSchema.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.edSchema.HideSelection = false;
            this.edSchema.Location = new System.Drawing.Point(296, 8);
            this.edSchema.Multiline = true;
            this.edSchema.Name = "edSchema";
            this.edSchema.ScrollBars = System.Windows.Forms.ScrollBars.Both;
            this.edSchema.Size = new System.Drawing.Size(829, 517);
            this.edSchema.TabIndex = 1;
            this.edSchema.WordWrap = false;
            // 
            // mainMenu
            // 
            this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuFile,
            this.menuItem1,
            this.mnuAbout});
            // 
            // mnuFile
            // 
            this.mnuFile.Index = 0;
            this.mnuFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuNew,
            this.mnuOpen,
            this.menuItem3,
            this.mnuSave,
            this.mnuSaveAs,
            this.menuItem2,
            this.mnuExit});
            this.mnuFile.Text = "&File";
            // 
            // mnuNew
            // 
            this.mnuNew.Index = 0;
            this.mnuNew.Text = "&New";
            this.mnuNew.Click += new System.EventHandler(this.mnuNew_Click);
            // 
            // mnuOpen
            // 
            this.mnuOpen.Index = 1;
            this.mnuOpen.Text = "&Open";
            this.mnuOpen.Click += new System.EventHandler(this.mnuOpen_Click);
            // 
            // menuItem3
            // 
            this.menuItem3.Index = 2;
            this.menuItem3.Text = "-";
            // 
            // mnuSave
            // 
            this.mnuSave.Index = 3;
            this.mnuSave.Text = "&Save";
            this.mnuSave.Click += new System.EventHandler(this.mnuSave_Click);
            // 
            // mnuSaveAs
            // 
            this.mnuSaveAs.Index = 4;
            this.mnuSaveAs.Text = "Save &As";
            this.mnuSaveAs.Click += new System.EventHandler(this.mnuSaveAs_Click);
            // 
            // menuItem2
            // 
            this.menuItem2.Index = 5;
            this.menuItem2.Text = "-";
            // 
            // mnuExit
            // 
            this.mnuExit.Index = 6;
            this.mnuExit.Text = "E&xit";
            this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click);
            // 
            // menuItem1
            // 
            this.menuItem1.Index = 1;
            this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuCompile});
            this.menuItem1.Text = "&Schema";
            // 
            // mnuCompile
            // 
            this.mnuCompile.Index = 0;
            this.mnuCompile.Text = "&Compile";
            this.mnuCompile.Click += new System.EventHandler(this.mnuCompile_Click);
            // 
            // mnuAbout
            // 
            this.mnuAbout.Index = 2;
            this.mnuAbout.Text = "&About";
            this.mnuAbout.Click += new System.EventHandler(this.mnuAbout_Click);
            // 
            // edSchemaErrors
            // 
            this.edSchemaErrors.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.edSchemaErrors.HideSelection = false;
            this.edSchemaErrors.Location = new System.Drawing.Point(296, 533);
            this.edSchemaErrors.Multiline = true;
            this.edSchemaErrors.Name = "edSchemaErrors";
            this.edSchemaErrors.ReadOnly = true;
            this.edSchemaErrors.ScrollBars = System.Windows.Forms.ScrollBars.Both;
            this.edSchemaErrors.Size = new System.Drawing.Size(829, 88);
            this.edSchemaErrors.TabIndex = 2;
            // 
            // gbSelectType
            // 
            this.gbSelectType.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.gbSelectType.Controls.Add(this.cbGlobalTypes);
            this.gbSelectType.Controls.Add(this.cbSimpleTypes);
            this.gbSelectType.Controls.Add(this.label2);
            this.gbSelectType.Controls.Add(this.label1);
            this.gbSelectType.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.gbSelectType.Location = new System.Drawing.Point(8, 525);
            this.gbSelectType.Name = "gbSelectType";
            this.gbSelectType.Size = new System.Drawing.Size(280, 96);
            this.gbSelectType.TabIndex = 3;
            this.gbSelectType.TabStop = false;
            this.gbSelectType.Text = "Select Type";
            // 
            // cbGlobalTypes
            // 
            this.cbGlobalTypes.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.cbGlobalTypes.Location = new System.Drawing.Point(88, 56);
            this.cbGlobalTypes.Name = "cbGlobalTypes";
            this.cbGlobalTypes.Size = new System.Drawing.Size(168, 21);
            this.cbGlobalTypes.Sorted = true;
            this.cbGlobalTypes.TabIndex = 3;
            this.cbGlobalTypes.SelectedIndexChanged += new System.EventHandler(this.cbGlobalTypes_SelectedIndexChanged);
            // 
            // cbSimpleTypes
            // 
            this.cbSimpleTypes.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.cbSimpleTypes.Items.AddRange(new object[] {
            "anyURI",
            "base64Binary",
            "boolean",
            "byte",
            "date",
            "dateTime",
            "decimal",
            "double",
            "duration",
            "ENTITIY",
            "float",
            "gDay",
            "gMonth",
            "gMonthDay",
            "gYear",
            "gYearMonth",
            "hexBinary",
            "ID",
            "IDREF",
            "imteger",
            "int",
            "language",
            "long",
            "Name",
            "NCName",
            "negativeInteger",
            "NMTOKEN",
            "nonNegativeInteger",
            "nonPositiveInteger",
            "normalizedString",
            "NOTATION",
            "positiveInteger",
            "QName",
            "short",
            "string",
            "time",
            "token",
            "unsignedByte",
            "unsignedInt",
            "unsignedLong",
            "unsignedShort"});
            this.cbSimpleTypes.Location = new System.Drawing.Point(88, 24);
            this.cbSimpleTypes.Name = "cbSimpleTypes";
            this.cbSimpleTypes.Size = new System.Drawing.Size(168, 21);
            this.cbSimpleTypes.Sorted = true;
            this.cbSimpleTypes.TabIndex = 2;
            this.cbSimpleTypes.SelectedIndexChanged += new System.EventHandler(this.cbSimpleTypes_SelectedIndexChanged);
            // 
            // label2
            // 
            this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.label2.Location = new System.Drawing.Point(8, 58);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(80, 16);
            this.label2.TabIndex = 1;
            this.label2.Text = "Global Types:";
            // 
            // label1
            // 
            this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.label1.Location = new System.Drawing.Point(8, 26);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(80, 16);
            this.label1.TabIndex = 0;
            this.label1.Text = "Simple Types:";
            // 
            // saveAsSchemaDialog
            // 
            this.saveAsSchemaDialog.DefaultExt = "xsd";
            // 
            // SchemaEditor
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(1132, 638);
            this.Controls.Add(this.gbSelectType);
            this.Controls.Add(this.edSchemaErrors);
            this.Controls.Add(this.edSchema);
            this.Controls.Add(this.tvSchema);
            this.Menu = this.mainMenu;
            this.Name = "SchemaEditor";
            this.Text = "XML Schema Editor";
            this.gbSelectType.ResumeLayout(false);
            this.ResumeLayout(false);
            this.PerformLayout();

		}
		#endregion


		#region Menu Commands

		#region Add Facets
		// There are several types of facets that can be added to a simple type.
		// This code adds a facet and specifies a default value (completely arbitrary)

		private void mnuFacetEnumeration_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaEnumerationFacet(), "1", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMaxExclusive_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMaxExclusiveFacet(), "101", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMaxInclusive_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMaxInclusiveFacet(), "100", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMinExclusive_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMinExclusiveFacet(), "0", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMinInclusive_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMinInclusiveFacet(), "1", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetFractionDigits_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaFractionDigitsFacet(), "2", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetLength_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaLengthFacet(), "16", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMaxLength_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMaxLengthFacet(), "16", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetMinLength_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaMinLengthFacet(), "1", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetTotalDigits_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaTotalDigitsFacet(), "8", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}


		private void mnuFacetPattern_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaPatternFacet(), "[0-9]", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}

		private void mnuFacetWhiteSpace_Click(object sender, System.EventArgs e)
		{
			bool ret=AddFacet(new XmlSchemaWhiteSpaceFacet(), "collapse", TreeViewImages.Facet);
			if (!ret)
			{
				MessageBox.Show("Cannot add an element to this item.");
			}
		}
		#endregion

		#region Add Annotation, Documentation, and AppInfo
		// create an annotation for the schema or for an annotatable object
		private void mnuAddAnnotation_Click(object sender, System.EventArgs e)
		{
			XmlSchemaAnnotation annot=new XmlSchemaAnnotation();
			TreeNode newNode=CreateNode("--annotation--");

			// if adding at the schema root level...
			if (newNode.Parent==tvSchema.Nodes[0])
			{
				AddToCollection(schema.Items, annot, newNode, TreeViewImages.Annotation);
			}
			else
			{
				// otherwise, get the object as an XmlSchemaAnnotated type
				XmlSchemaAnnotated obj=newNode.Parent.Tag as XmlSchemaAnnotated;
				if (obj != null)
				{
					// if it exists, add the annotation
					obj.Annotation=annot;
					newNode.Tag=annot;
					newNode.ImageIndex=(int)TreeViewImages.Annotation;
					newNode.SelectedImageIndex=(int)TreeViewImages.Annotation;
					CompileSchema();
				}
				else
				{
					// otherwise, tell the user annotation cannot be added to this type.
					newNode.Parent.Nodes.Remove(newNode);
					MessageBox.Show("Cannot create an annotation for this item.");
				}
			}
		}

		private void mnuAddDocumentation_Click(object sender, System.EventArgs e)
		{
			bool success=false;
			XmlSchemaAnnotation annot=tvSchema.SelectedNode.Tag as XmlSchemaAnnotation;
			// if the parent node is an annotation type...
			if (annot != null)
			{
				// ...then add the documentation type
				TreeNode newNode=CreateNode("--documentation--");
				XmlSchemaDocumentation doc=new XmlSchemaDocumentation();
				doc.Markup=TextToNodeArray("Documentation");
				annot.Items.Add(doc);
				newNode.Tag=doc;
				newNode.ImageIndex=(int)TreeViewImages.Annotation;
				newNode.SelectedImageIndex=(int)TreeViewImages.Annotation;
				CompileSchema();
				success=true;
			}
			if (!success)
			{
				// otherwise create the annotation type first
				mnuAddAnnotation_Click(sender, e);
				annot=tvSchema.SelectedNode.Tag as XmlSchemaAnnotation;
				// if successful in adding the annotation type, add the documentation type now
				if (annot != null)
				{
					mnuAddDocumentation_Click(sender, e);
				}
			}
		}

		private void mnuAddAppInfo_Click(object sender, System.EventArgs e)
		{
			bool success=false;
			XmlSchemaAnnotation annot=tvSchema.SelectedNode.Tag as XmlSchemaAnnotation;
			// if the parent node is an annotation type...
			if (annot != null)
			{
				// ...then add the AppInfo type
				TreeNode newNode=CreateNode("--app info--");
				XmlSchemaAppInfo doc=new XmlSchemaAppInfo();
				doc.Markup=TextToNodeArray("Application Information");
				annot.Items.Add(doc);
				newNode.Tag=doc;
				newNode.ImageIndex=(int)TreeViewImages.Annotation;
				newNode.SelectedImageIndex=(int)TreeViewImages.Annotation;
				CompileSchema();
				success=true;
			}
			if (!success)
			{
				// otherwise create the annotation type first
				mnuAddAnnotation_Click(sender, e);
				annot=tvSchema.SelectedNode.Tag as XmlSchemaAnnotation;
				// if successful in creating the annotation type, add the AppInfo type now
				if (annot != null)
				{
					mnuAddAppInfo_Click(sender, e);
				}
			}
		}

		#endregion

		#region Add Attribute
		// Can only be added to schema root as a global or complex type.
		// For complex types, the attribute can reference a global type.
		// An optional type can be specified referring to a simple type.
		// If the type isn't used, the attribute must define a simple type.
		private void mnuAddAttribute_Click(object sender, System.EventArgs e)
		{
			TreeNode newNode=CreateNode("Attribute");
			XmlSchemaAttribute attrib=new XmlSchemaAttribute();
			attrib.Name="Attribute";
			attrib.SchemaTypeName=new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema");

			// root node?
			if (newNode.Parent==tvSchema.Nodes[0])
			{
				// add to root of schema.  An global attribute cannot reference a global type
				AddToCollection(schema.Items, attrib, newNode, TreeViewImages.Attribute);
				cbGlobalTypes.Items.Add(new GlobalElementType(attrib.Name, attrib));
				cbGlobalTypes.Enabled=false;
				cbSimpleTypes.SelectedItem=-1;
				cbSimpleTypes.Enabled=true;
				cbSimpleTypes.SelectedItem="string";
			}
			else
			{
				// an attribute can only be added to a complex type
				XmlSchemaComplexType ct=newNode.Parent.Tag as XmlSchemaComplexType;
				if (ct != null)
				{
					// and can reference a global attribute, so enable the global combobox
					AddToCollection(ct.Attributes, attrib, newNode, TreeViewImages.Attribute);
					cbGlobalTypes.SelectedItem=-1;
					cbGlobalTypes.Enabled=true;
					cbSimpleTypes.SelectedItem="string";
					cbSimpleTypes.Enabled=true;
				}
				else
				{
					newNode.Parent.Nodes.Remove(newNode);
					MessageBox.Show("Cannot create an attribute for this item.");
				}
			}
		}
		#endregion

		#region Add Element
		// An element can be added to the schema or to a complex type.
		// If adding to an element, convert the element to a complex type.
		// An element can be added to a global complex type or to a local complex type.
		private void mnuAddElement_Click(object sender, System.EventArgs e)
		{
			TreeNode newNode=CreateNode("Element");
			XmlSchemaElement element=new XmlSchemaElement();
			element.Name="Element";
			element.SchemaTypeName=new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema");

			// root node?
			if (newNode.Parent==tvSchema.Nodes[0])
			{
				// add to root of schema.  A global element can reference another global type
				AddToCollection(schema.Items, element, newNode, TreeViewImages.Element);
				cbGlobalTypes.Items.Add(new GlobalElementType(element.Name, element));
				cbGlobalTypes.Enabled=true;
				cbSimpleTypes.SelectedItem=-1;
				cbSimpleTypes.Enabled=true;
				cbSimpleTypes.SelectedItem="string";
			}
			else
			{
				// otherwise, an element must be part of a complex type
				bool ret=AddToComplexType(newNode.Parent.Tag, element, newNode, TreeViewImages.Element);
				if (!ret)
				{
					// not successful
					newNode.Parent.Nodes.Remove(newNode);
					MessageBox.Show("Cannot add an element to this item.");
				}
				else
				{
					// successful
					cbGlobalTypes.SelectedItem=-1;
					cbGlobalTypes.Enabled=true;
					cbSimpleTypes.SelectedItem="string";
					cbSimpleTypes.Enabled=true;
				}
			}
		}
		#endregion

		#region Add Simple Type
		// A simple type can be added as a global type or as a local member of a complex type.
		// A simple type cannot contain elements or attributes.
		// Simple types are derived from basic types or other simple types.
		// The complex type can either be a global definition or a local complex type.
		// When adding to a complex type, the simple type must be wrapped in an element.
		private void mnuAddSimpleType_Click(object sender, System.EventArgs e)
		{
			TreeNode newNode=CreateNode("SimpleType");

			XmlSchemaSimpleType simpleType=new XmlSchemaSimpleType();
			simpleType.Name="SimpleType";
			XmlSchemaSimpleTypeRestriction restriction=new XmlSchemaSimpleTypeRestriction();
			restriction.BaseTypeName=new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema");
			simpleType.Content=restriction;

			// root node?
			if (newNode.Parent==tvSchema.Nodes[0])
			{
				// add to root of schema.  A global simple type cannot reference another global
				AddToCollection(schema.Items, simpleType, newNode, TreeViewImages.SimpleType);
				cbGlobalTypes.Items.Add(new GlobalElementType(simpleType.Name, simpleType));
				cbGlobalTypes.Enabled=false;
				cbSimpleTypes.SelectedItem=-1;
				cbSimpleTypes.Enabled=true;
				cbSimpleTypes.SelectedItem="string";
			}
			else
			{
				// if not a root node, then it must be created as an element of simple type...
				XmlSchemaElement el=new XmlSchemaElement();
				el.Name="SimpleType";
				el.SchemaType=simpleType;
				simpleType.Name=null;
				// ...as a subnode to a complex type
				bool ret=AddToComplexType(newNode.Parent.Tag, el, newNode, TreeViewImages.SimpleType);
				if (!ret)
				{
					// failure
					newNode.Parent.Nodes.Remove(newNode);
					MessageBox.Show("Cannot add a simple type to this item.");
				}
				else
				{
					// success.  Can reference a global simple type
					cbGlobalTypes.SelectedItem=-1;
					cbGlobalTypes.Enabled=true;
					cbSimpleTypes.SelectedItem="string";
					cbSimpleTypes.Enabled=true;
				}
			}
		}
		#endregion

		#region Add Complex Type
		// A complex type can be added as a global type to the schema or as a complex element.
		// If adding to an element, change the element to a complex type.
		// When adding to a complex type, the complex type must be wrapped in an element.
		private void mnuAddComplexType_Click(object sender, System.EventArgs e)
		{
			TreeNode newNode=CreateNode("ComplexType");

			XmlSchemaComplexType complexType=new XmlSchemaComplexType();
			XmlSchemaSequence sequence=new XmlSchemaSequence();
			complexType.Particle=sequence;
			complexType.Name="ComplexType";

			// root node?
			if (newNode.Parent==tvSchema.Nodes[0])
			{
				// add to root.  A complex type has no type reference information.
				AddToCollection(schema.Items, complexType, newNode, TreeViewImages.ComplexType);
				cbGlobalTypes.Items.Add(new GlobalElementType(complexType.Name, complexType));
				cbSimpleTypes.SelectedItem=-1;
				cbGlobalTypes.SelectedItem=-1;
				cbSimpleTypes.Enabled=false;
				cbGlobalTypes.Enabled=false;
			}
			else
			{
				// if not at root, create an element of complex type...
				XmlSchemaElement el=new XmlSchemaElement();
				el.Name="ComplexType";
				el.SchemaType=complexType;
				complexType.Name=null;
				// ...that is added as a subnode to a complex type.
				bool ret=AddToComplexType(newNode.Parent.Tag, el, newNode, TreeViewImages.ComplexType);
				if (!ret)
				{
					// failure
					newNode.Parent.Nodes.Remove(newNode);
					MessageBox.Show("Cannot add a complex type to this item.");
				}
				else
				{
					// success.  No type is referenced.
					cbSimpleTypes.SelectedItem=-1;
					cbGlobalTypes.SelectedItem=-1;
					cbSimpleTypes.Enabled=false;
					cbGlobalTypes.Enabled=false;
				}
			}
		}
		#endregion

		#region New
		private void mnuNew_Click(object sender, System.EventArgs e)
		{
			CreateRootNode();		// create a new treeview root node
			schema=new XmlSchema();	// create a new schema
			CompileSchema();		// compile and show it
			fileName=null;			// no filename
		}
		#endregion

		#region Open
		// open an existing XSD file
		private void mnuOpen_Click(object sender, System.EventArgs e)
		{
			openSchemaDialog.DefaultExt="xsd";
			openSchemaDialog.CheckFileExists=true;
			openSchemaDialog.Filter="XSD Files (*.xsd)|*.xsd|All Files (*.*)|*.*";
			DialogResult res=openSchemaDialog.ShowDialog();
			if (res==DialogResult.OK)
			{
				try
				{
					StreamReader tr=new StreamReader(openSchemaDialog.FileName);
					schema=XmlSchema.Read(tr, new ValidationEventHandler(SchemaValidationHandler));
					tr.Close();
					CompileSchema();
					CreateRootNode();
					DecodeSchema(schema, tvSchema.Nodes[0]);
					tvSchema.ExpandAll();
					fileName=openSchemaDialog.FileName;
				}
				catch(Exception err)
				{
					edSchemaErrors.Text=err.ToString();
				}
			}
		}
		#endregion

		#region Save, Save As, Exit, About
		// save the current XSD
		private void mnuSave_Click(object sender, System.EventArgs e)
		{
			if (fileName==null)
			{
				mnuSaveAs_Click(sender, e);
			}
			else
			{
				CompileSchema();
				StreamWriter sw=new StreamWriter(fileName, false, System.Text.Encoding.UTF8);
				sw.Write(edSchema.Text);
				sw.Flush();
				sw.Close();
			}
		}

		// save the current XSD as...
		private void mnuSaveAs_Click(object sender, System.EventArgs e)
		{
			DialogResult res=saveAsSchemaDialog.ShowDialog();
			if (res==DialogResult.OK)
			{
				fileName=saveAsSchemaDialog.FileName;
				CompileSchema();
				StreamWriter sw=new StreamWriter(fileName, false, System.Text.Encoding.UTF8);
				sw.Write(edSchema.Text);
				sw.Flush();
				sw.Close();

			}
		}

		private void mnuExit_Click(object sender, System.EventArgs e)
		{
			Close();		// signal form to close
		}

		// info
		private void mnuAbout_Click(object sender, System.EventArgs e)
		{
			MessageBox.Show("XML Schema Editor\r\n\r\nversion 1.0\r\n\r\n(c)2003 Marc Clifton\r\n\r\nThis program may be freely distributed.");
		}
		#endregion

		#region Compile
		private void mnuCompile_Click(object sender, System.EventArgs e)
		{
			// 1. read the XSD from the edit box into a schema
			// 2. compile it
			// 3. create a new tree view
			// 4. decode the schema into the tree view
			// 5. show the tree
			try
			{
				StringReader sr=new StringReader(edSchema.Text);
				schema=XmlSchema.Read(sr, new ValidationEventHandler(SchemaValidationHandler));
				CompileSchema();
				CreateRootNode();
				DecodeSchema(schema, tvSchema.Nodes[0]);
				tvSchema.ExpandAll();
			}
			catch(Exception err)
			{
				edSchemaErrors.Text=err.ToString();
			}
		}
		#endregion

		#region Remove Node
		// The parent type determines from what list the selected item must be removed.
		// Use the image index in the tree view to figure out the parent type.
		private void mnuRemoveNode_Click(object sender, System.EventArgs e)
		{
			TreeNode tnParent=tvSchema.SelectedNode.Parent;
			XmlSchemaObject obj=tvSchema.SelectedNode.Tag as XmlSchemaObject;
			bool success=false;
			// if the node to remove has a parent and is of an XmlSchemaObject type...
			if ( (tnParent != null) && (obj != null) )
			{
				// look at the tree node image index to figure out what the parent is!
				switch ((TreeViewImages)tnParent.ImageIndex)
				{
					// if the parent is the schema root:
					case TreeViewImages.Schema:
					{
						// remove the object from the schema and from the global list
						schema.Items.Remove(obj);
						int idx=cbGlobalTypes.FindStringExact(tvSchema.SelectedNode.Text);
						if (idx != -1)
						{
							cbGlobalTypes.Items.RemoveAt(idx);
						}
						success=true;
						break;
					}

					// if the parent is an annotation type
					case TreeViewImages.Annotation:
					{
						XmlSchemaAnnotation annot=tnParent.Tag as XmlSchemaAnnotation;
						if (annot != null)
						{
							annot.Items.Remove(obj);
							success=true;
						}
						break;
					}

					// if the parent is a simple type
					case TreeViewImages.SimpleType:
					{
						// a simple type can have an annotation or a facet type as children
						XmlSchemaSimpleType st=tnParent.Tag as XmlSchemaSimpleType;
						if (obj is XmlSchemaAnnotation)
						{
							// remove from annotation list if it's an annotation type
							st.Annotation.Items.Remove(obj);
							success=true;
						}
						else if (obj is XmlSchemaFacet)
						{
							XmlSchemaSimpleTypeRestriction rest=st.Content as XmlSchemaSimpleTypeRestriction;
							if (rest != null)
							{
								// remove from facet list if it's a facet type
								rest.Facets.Remove(obj);
								success=true;
							}
						}
						break;
					}

					// if the parent is a complex type...
					case TreeViewImages.ComplexType:
					{
						XmlSchemaComplexType ct=tnParent.Tag as XmlSchemaComplexType;
						if (ct != null)
						{
							// then we are removing an attribute
							if (obj is XmlSchemaAttribute)
							{
								ct.Attributes.Remove(obj);
								success=true;
							}
							// or an annotation
							else if (obj is XmlSchemaAnnotation)
							{
								ct.Annotation.Items.Remove(obj);
								success=true;
							}
							// or an element type
							else
							{
								XmlSchemaSequence seq=ct.Particle as XmlSchemaSequence;
								if (seq != null)
								{
									seq.Items.Remove(obj);
									success=true;
								}
							}
						}
						break;
					}
				}
			}
			// if successful, remove the node from the tree view
			if (success)
			{
				tnParent.Nodes.Remove(tvSchema.SelectedNode);
				CompileSchema();
			}
			else
			{
				MessageBox.Show("Unable to remove this node");
			}
		}
		#endregion

		#endregion

		#region Schema Validation Handler
		// report any errors to the schema error edit box
		private void SchemaValidationHandler(object sender, ValidationEventArgs args) 
		{
			Console.WriteLine(args.Message);
			edSchemaErrors.Text+=args.Message+"\r\n";
		}
		#endregion

		#region Events

		#region TreeView PreEventLabelChanged and EventLabelChanged
		// exclude certain tree nodes from being editable
		private void PreEventLabelChanged(object sender, NodeLabelEditEventArgs e)
		{
			prevLabel=tvSchema.SelectedNode.Text;
			if ( (e.Node.Tag is XmlSchemaFacet) ||
				(e.Node.Tag is XmlSchemaAnnotation) || 
				(e.Node.Tag is XmlSchemaDocumentation) ||
				(e.Node.Tag is XmlSchemaAppInfo) )
			{
				e.Node.EndEdit(false);
			}
		}

		private void EventLabelChanged(object sender, NodeLabelEditEventArgs e)
		{
			// if a node is selected...
			if (e.Node != null)
			{
				// and a label has been changed... (e.Label==null if ESC key pressed)
				if (e.Label != null)
				{
					// then change the name of the type in the schema
					UpdateTypeAndName(null, e.Label, null);

					// if this is a root node...
					if (e.Node.Parent == tvSchema.Nodes[0])
					{
						// ...then also change the name in the global list
						// (this is not case sensitive!)
						int idx=cbGlobalTypes.FindStringExact(prevLabel);
						if (idx != -1)
						{
							cbGlobalTypes.Items[idx]=new GlobalElementType(e.Label, ((GlobalElementType)cbGlobalTypes.Items[idx]).type);
						}
					}
				}
			}
		}
		#endregion

		#region EventTreeViewKeyPress
		// shortcuts:
		// F2 - edit tree node label
		// Ctrl+A - bring up popup menu to Add a subnode
		// Ctrl+T - go to Top of tree
		// Ctrl+P - go to Parent of currently selected node
		private void EventTreeViewKeyUp(object sender, KeyEventArgs e)
		{
			e.Handled=false;
			// F2
			if (e.KeyCode==Keys.F2)
			{
				if (tvSchema.SelectedNode != tvSchema.Nodes[0])
				{
					tvSchema.SelectedNode.BeginEdit();
					e.Handled=true;
				}
			}
			// Ctrl+A
			else if ( (e.KeyCode==Keys.A) && (e.Modifiers==Keys.Control) )
			{
				e.Handled=true;
				tvcmSchema.Show(this, tvSchema.Location+new Size(50, 50));
			}
			// Ctrl+T
			else if ( (e.KeyCode==Keys.T) && (e.Modifiers==Keys.Control) )
			{
				e.Handled=true;
				tvSchema.SelectedNode=tvSchema.Nodes[0];
			}
			// Ctrl+P
			else if ( (e.KeyCode==Keys.P) && (e.Modifiers==Keys.Control) )
			{
				e.Handled=true;
				TreeNode node=tvSchema.SelectedNode.Parent;
				if (node != null)
				{
					tvSchema.SelectedNode=node;
				}
			}
		}
		#endregion

		#region Schema Text Box Lost Focus
		private void EventSchemaTextBoxLostFocus(object sender, EventArgs e)
		{
			mnuCompile_Click(sender, e);
		}
		#endregion

		#region TreeView MouseDown
		// On a mouse down, we want to select the node on which the mouse clicked.
		// This way we know what node the user right-clicked on when adding sub-nodes
		private void EventMouseDown(object sender, MouseEventArgs e)
		{
			TreeNode tn=tvSchema.GetNodeAt(e.X, e.Y);
			if (tn != null)
			{
				tvSchema.SelectedNode=tn;
			}
		}
		#endregion

		#region TreeView AfterSelect
		// After selecting a node, we want to:
		// 1. highlight the line in the schema that corresponds to the tree node
		// 2. update the simple and global type combo boxes to show what the type is for the selected node.
		private void tvSchema_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
		{
			XmlSchemaObject obj=e.Node.Tag as XmlSchemaObject;
			// if this is a schema object...
			if (obj != null)
			{
				// find the corresponding line in the XSD source and highlight it
				if ( (obj.LineNumber != 0) && (obj.LineNumber < edSchema.Lines.Length) )
				{
					int length=0;
					for (int i=0; i<obj.LineNumber-1; i++)
					{
						// get the length of the line including CRLF
						length+=edSchema.Lines[i].Length+2;
					}
					// highlight the line
					edSchema.Select(length, edSchema.Lines[obj.LineNumber-1].Length);
				}

				// Update simple and global type combo boxes.
				// Get the name of the element type so that we can find it in the simple or global type list
				XmlQualifiedName name=null;		// assume failure
				if (obj is XmlSchemaAttribute)
				{
					// this is easy.
					name=((XmlSchemaAttribute)obj).SchemaTypeName;
				}
				else if (obj is XmlSchemaSimpleType)
				{
					// if it's a simple type, get the restriction type, if it exists
					XmlSchemaSimpleTypeRestriction restriction=((XmlSchemaSimpleType)obj).Content as XmlSchemaSimpleTypeRestriction;
					if (restriction != null)
					{
						name=restriction.BaseTypeName;
					}
				}
				else if (obj is XmlSchemaElement)
				{
					// if it's an element, determine if it's a simple type subnode of a complex type...
					// and then get the restriction type, if it exists
					XmlSchemaElement el=obj as XmlSchemaElement;
					if (el.SchemaType is XmlSchemaSimpleType)
					{
						XmlSchemaSimpleType st=el.SchemaType as XmlSchemaSimpleType;
						XmlSchemaSimpleTypeRestriction rest=st.Content as XmlSchemaSimpleTypeRestriction;
						if (rest != null)
						{
							name=rest.BaseTypeName;
						}
					}
					else
					{
						// otherwise get the element name
						name=el.SchemaTypeName;

						// if the name is null, then there must be a reference instead
						if (name.Name=="")
						{
							name=el.RefName;
						}
					}
				}

				// select the name from either the simple type list or the global element type list
				if (name != null)
				{
					// see if the name exists in the simple type list
					int idx=cbSimpleTypes.FindStringExact(name.Name);
					cbSimpleTypes.SelectedIndex=idx;
					cbSimpleTypes.Enabled=true;

					// see if the name exists in the complex type list
					idx=cbGlobalTypes.FindStringExact(name.Name);
					cbGlobalTypes.SelectedIndex=idx;
					cbGlobalTypes.Enabled=true;
				}
				else
				{
					// if there is no name, then disable the comboboxes
					cbSimpleTypes.SelectedIndex=-1;
					cbGlobalTypes.SelectedIndex=-1;
					cbSimpleTypes.Enabled=false;
					cbGlobalTypes.Enabled=false;
				}
			}
			else
			{
				// if this isn't a schema object, then disable the comboboxes
				cbSimpleTypes.SelectedIndex=-1;
				cbGlobalTypes.SelectedIndex=-1;
				cbSimpleTypes.Enabled=false;
				cbGlobalTypes.Enabled=false;
			}
		}
		#endregion

		#region cbSimpleTypes Index Changed
		// the user has selected a simple type.  Select it and clear the global type combo box.
		private void cbSimpleTypes_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			if (cbSimpleTypes.SelectedIndex != -1)
			{
				UpdateTypeAndName(cbSimpleTypes.SelectedItem.ToString(), null, "http://www.w3.org/2001/XMLSchema");
				cbGlobalTypes.SelectedIndex=-1;
			}
		}
		#endregion

		#region cbGlobalTypes Index Changed
		// the user has selected a global type.  Select it and clear the simple type combo box.
		private void cbGlobalTypes_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			if (cbGlobalTypes.SelectedIndex != -1)
			{
				UpdateTypeAndName(cbGlobalTypes.SelectedItem.ToString(), null, null);
				cbSimpleTypes.SelectedIndex=-1;
			}
		}
		#endregion


		#endregion

		#region Misc. Helpers

		#region CreateRootNode
		// This helper function destroys the existing tree and creates a new tree.
		// It also clears the global type list, since there are no global types defined
		//	with a blank tree.
		private void CreateRootNode()
		{
			tvSchema.Nodes.Clear();
			TreeNode rootNode=new TreeNode("Schema:");
			tvSchema.Nodes.Add(rootNode);
			rootNode.ImageIndex=(int)TreeViewImages.Schema;
			rootNode.SelectedImageIndex=(int)TreeViewImages.Schema;
			cbGlobalTypes.Items.Clear();
		}
		#endregion

		#region CompileSchema
		// Compile the schema as it exists in the XmlSchema structure, displaying any
		// errors in the schema error edit box and displaying the schema itself in
		// the schema edit box.
		private void CompileSchema()
		{
			edSchemaErrors.Text="";
			schema.Compile(new ValidationEventHandler(SchemaValidationHandler));
			StringWriter sw=new StringWriter();
			schema.Write(sw);
			edSchema.Text=sw.ToString();
		}
		#endregion

		#region CreateNode
		// This helper function creates a subnode off of the selected node and requests
		// that the node label be immediately editable.
		private TreeNode CreateNode(string name)
		{
			TreeNode tn=tvSchema.SelectedNode;
			TreeNode newNode=new TreeNode(name);
			tn.Nodes.Add(newNode);
			tn.Expand();
			tvSchema.SelectedNode=newNode;
			newNode.BeginEdit();
			return newNode;
		}
		#endregion

		#region AddToCollection
		// Add a schema type to the specified schema object collection.
		// The tree node references the schema type being added.
		// The image indices are set.
		// The schema is recompiled, which shows any errors and updates the schema display.
		void AddToCollection(XmlSchemaObjectCollection coll, XmlSchemaObject obj, TreeNode node, TreeViewImages imgIdx)
		{
			coll.Add(obj);
			node.Tag=obj;
			node.ImageIndex=(int)imgIdx;
			node.SelectedImageIndex=(int)imgIdx;
			CompileSchema();
		}
		#endregion

		#region ChangeElementToComplexType
		// When adding a subnode to an element or a simple type, the node must be changed to a complex type.
		private XmlSchemaComplexType ChangeElementToComplexType(XmlSchemaElement el, TreeNode tn)
		{
			// if the element is currently a reference, we need to remove the reference
			// and set the name to something, which in this case is the old ref name.
			if (el.RefName != null)
			{
				el.Name=el.RefName.Name;
				el.RefName=null;
			}
			// creat the complex type.
			XmlSchemaComplexType ct=new XmlSchemaComplexType();
			el.SchemaType=ct;
			// a complex type cannot have a type name
			el.SchemaTypeName=null;
			// create the sequence
			XmlSchemaSequence sequence=new XmlSchemaSequence();
			ct.Particle=sequence;

			// update the image indices
			tn.ImageIndex=(int)TreeViewImages.ComplexType;
			tn.SelectedImageIndex=(int)TreeViewImages.ComplexType;

			return ct;
		}
		#endregion

		#region AddToComplexType
		// add a type to a complex type
		private bool AddToComplexType(object obj, XmlSchemaObject item, TreeNode newNode, TreeViewImages imgIdx)
		{
			bool success=true;
			XmlSchemaElement el=obj as XmlSchemaElement;
			XmlSchemaComplexType complexType=obj as XmlSchemaComplexType;

			// is it an element...
			if (el != null)
			{
				// of complex type (so we know it's a local complex type, not a global one!)
				XmlSchemaComplexType ct=el.SchemaType as XmlSchemaComplexType;
				if (ct != null)
				{
					// does it have a sequence?
					XmlSchemaSequence seq=ct.Particle as XmlSchemaSequence;
					if (seq != null)
					{
						// yes--add it to the sequence collection
						AddToCollection(seq.Items, item, newNode, imgIdx);
					}
					else
					{
						// no--we can't add it.
						MessageBox.Show("Complex type is missing sequence!");
						success=false;
					}
				}
				else
				{
					// change the basic element to a complex type by adding a sequence and then
					// add the sub-element
					ct=ChangeElementToComplexType(el, newNode.Parent);
					AddToCollection(((XmlSchemaSequence)ct.Particle).Items, item, newNode, imgIdx);
				}
			}
			// or is it a global complex type...
			else	if (complexType != null)
			{
				XmlSchemaSequence seq=complexType.Particle as XmlSchemaSequence;
				// which should have a sequence!
				if (seq != null)
				{
					// yes--add it to the collection
					AddToCollection(seq.Items, item, newNode, imgIdx);
				}
				else
				{
					// no--we can't add it.
					MessageBox.Show("Complex type is missing sequence!");
					success=false;
				}
			}
			else
			{
				// failure--current node is not an element and not a complex type
				success=false;
			}
			return success;
		}
		#endregion

		#region UpdateTypeAndName
		// This is a dual purpose function that updates either the type or the name.
		// It can also update both at once, but isn't used in that way in this program.
		// Pass in a null for typeName if only changing the name.
		// Pass in a null for name if only changing the typeName.
		// Pass in a null for the nameSpace if the typeName is a global type.
		private void UpdateTypeAndName(string typeName, string name, string nameSpace)
		{
			// Is the type referenced by the tree node an XmlSchemaObject?
			XmlSchemaObject obj=tvSchema.SelectedNode.Tag as XmlSchemaObject;
			if (obj != null)
			{
				// is it an attribute?
				if (obj is XmlSchemaAttribute)
				{
					XmlSchemaAttribute attrib=obj as XmlSchemaAttribute;
					// if we're changing the name:
					if (name != null)
					{
						attrib.Name=name;
						CompileSchema();
					}
					// if we're changing the type:
					if (typeName != null)
					{
						// if the name refers to a global attribute, then use ref instead of type
						int idx=cbGlobalTypes.FindStringExact(typeName);
						GlobalElementType glet=null;
						if (idx != -1)
						{
							glet=cbGlobalTypes.Items[idx] as GlobalElementType;
						}
						// if a global exists of this type...
						if ( (glet != null) && (glet.type is XmlSchemaAttribute) )
						{
							// then get rid of the type name and use a ref instead
							attrib.SchemaTypeName=null;
							attrib.RefName=new XmlQualifiedName(typeName, nameSpace);
							// can't have a name
							attrib.Name=null;
						}
						else
						{
							// otherwise, use a type name and get rid of the ref
							attrib.SchemaTypeName=new XmlQualifiedName(typeName, nameSpace);
							attrib.RefName=null;
							if (attrib.Name==null)
							{
								// if changing from ref to type, we need some sort of default name
								attrib.Name=tvSchema.SelectedNode.Text;
							}
						}
						CompileSchema();
						// update the tree node name
						tvSchema.SelectedNode.Text=attrib.QualifiedName.Name;
					}
				}
				// is it an element?
				else if (obj is XmlSchemaElement)
				{
					XmlSchemaElement el=obj as XmlSchemaElement;
					// if we're changing the name:
					if (name != null)
					{
						el.Name=name;
						CompileSchema();
					}

					// if we're changing the type:
					if (typeName != null)
					{
						if (el.SchemaType is XmlSchemaSimpleType)
						{
							XmlSchemaSimpleType st=el.SchemaType as XmlSchemaSimpleType;
							XmlSchemaSimpleTypeRestriction rest=st.Content as XmlSchemaSimpleTypeRestriction;
							if (rest != null)
							{
								rest.BaseTypeName=new XmlQualifiedName(typeName, nameSpace);
								CompileSchema();
							}
						}
						else
						{
							// if the name refers to a global element, then use ref instead of type
							// Same deal as for changing the element type name.
							// Since the SchemaTypeName and RefName are not part of any base class shared
							// between the SchemaXmlAttribute and SchemaXmlElement, we need separate code.
							int idx=cbGlobalTypes.FindStringExact(typeName);
							GlobalElementType glet=null;
							if (idx != -1)
							{
								glet=cbGlobalTypes.Items[idx] as GlobalElementType;
							}
							if ( (glet != null) && (glet.type is XmlSchemaElement) )
							{
								el.SchemaTypeName=null;
								el.RefName=new XmlQualifiedName(typeName, nameSpace);
								el.Name=null;
							}
							else
							{
								el.SchemaTypeName=new XmlQualifiedName(typeName, nameSpace);
								el.RefName=null;
								if (el.Name==null)
								{
									el.Name=tvSchema.SelectedNode.Text;
								}
							}
							CompileSchema();
							tvSchema.SelectedNode.Text=el.QualifiedName.Name;
						}
					}
				}
				// is it a simple type?
				else if (obj is XmlSchemaSimpleType)
				{
					XmlSchemaSimpleType st=obj as XmlSchemaSimpleType;
					// if we're changing the name:
					if (name != null)
					{
						st.Name=name;
						CompileSchema();
					}

					// if we're changing the type name:
					if (typeName != null)
					{
						// this must be done in the Restriction object
						XmlSchemaSimpleTypeRestriction restriction=st.Content as XmlSchemaSimpleTypeRestriction;
						if (restriction != null)
						{
							restriction.BaseTypeName=new XmlQualifiedName(typeName, nameSpace);
							CompileSchema();
							cbGlobalTypes.SelectedIndex=-1;
						}
					}
				}
				// is it a complex type?
				else if (obj is XmlSchemaComplexType)
				{
					// if we're changing the name:
					if (name != null)
					{
						((XmlSchemaComplexType)obj).Name=name;
						CompileSchema();
					}
					// there is no such thing as changing the type of a complex type
				}
			}
		}
		#endregion

		#region Add Facet
		// Add a facet to a simple type.
		bool AddFacet(XmlSchemaFacet facet, string val, TreeViewImages imgIdx)
		{
			// get the simple type.
			XmlSchemaSimpleType st=tvSchema.SelectedNode.Tag as XmlSchemaSimpleType;

			// assume failure
			XmlSchemaSimpleTypeRestriction rs=null;
			bool success=false;

			// if the simple type exists, get the restriction type
			if (st != null)
			{
				rs=st.Content as XmlSchemaSimpleTypeRestriction;
			}

			// if the restriction type exists...
			if (rs != null)
			{
				// create the node and add it to the facet collection
				TreeNode newNode=CreateNode(facet.ToString());
				facet.Value=val;
				rs.Facets.Add(facet);
				CompileSchema();
				success=true;
			}
			return success;
		}
		#endregion

		#region TextToNodeArray
		// a helper to create some default documentation text.
		public static XmlNode[] TextToNodeArray(string text) 
		{
			XmlDocument doc = new XmlDocument();
			return new XmlNode[1] {doc.CreateTextNode(text)};
		}
		#endregion

		#endregion
				
		#region DecodeSchema

		// stub that wraps the actual decoding in a try block so we can display errors
		private void DecodeSchema(XmlSchema schema, TreeNode node)
		{
			try
			{
				DecodeSchema2(schema, node);
			}
			catch(Exception err)
			{
				edSchemaErrors.Text=err.ToString();
			}
		}

		// recursive decoder
		private TreeNode DecodeSchema2(XmlSchemaObject obj, TreeNode node)
		{
			TreeNode newNode=node;

			// convert the object to all types and then check what type actually exists
			XmlSchemaAnnotation annot=obj as XmlSchemaAnnotation;
			XmlSchemaAttribute attrib=obj as XmlSchemaAttribute;
			XmlSchemaFacet facet=obj as XmlSchemaFacet;
			XmlSchemaDocumentation doc=obj as XmlSchemaDocumentation;
			XmlSchemaAppInfo appInfo=obj as XmlSchemaAppInfo;
			XmlSchemaElement element=obj as XmlSchemaElement;
			XmlSchemaSimpleType simpleType=obj as XmlSchemaSimpleType;
			XmlSchemaComplexType complexType=obj as XmlSchemaComplexType;

			// If the current node is the root node of the tree, then we are
			// possibly adding a global attribute, element, simple type, or complex type.
			if (node==tvSchema.Nodes[0])
			{
				if (attrib != null)
				{
					if (attrib.Name != null)
					{
						// add to global list
						cbGlobalTypes.Items.Add(new GlobalElementType(attrib.Name, attrib));
					}
				}
				else	if (element != null)
				{
					if (element.Name != null)
					{
						// add to global list
						cbGlobalTypes.Items.Add(new GlobalElementType(element.Name, element));
					}
				}
				else if (simpleType != null)
				{
					if (simpleType.Name != null)
					{
						// add to global list
						cbGlobalTypes.Items.Add(new GlobalElementType(simpleType.Name, simpleType));
					}
				}
				else if (complexType != null)
				{
					if (complexType.Name != null)
					{
						// add to global list
						cbGlobalTypes.Items.Add(new GlobalElementType(complexType.Name, complexType));
					}
				}
			}

			// if annotation, add a tree node and recurse for documentation and app info
			if (annot != null)
			{
				newNode=new TreeNode("--annotation--");
				newNode.Tag=annot;
				newNode.ImageIndex=4;
				newNode.SelectedImageIndex=4;
				node.Nodes.Add(newNode);
				foreach (XmlSchemaObject schemaObject in annot.Items)
				{
					DecodeSchema2(schemaObject, newNode);
				}
			}
			else
				// if attribute, add a tree node
				if (attrib != null)
			{
				newNode=new TreeNode(attrib.QualifiedName.Name);
				newNode.Tag=attrib;
				newNode.ImageIndex=7;
				newNode.SelectedImageIndex=7;
				node.Nodes.Add(newNode);
			}
			else
				// if facet, add a tree node
				if (facet != null)
			{
				newNode=new TreeNode(facet.ToString());
				newNode.Tag=facet;
				newNode.ImageIndex=8;
				newNode.SelectedImageIndex=8;
				node.Nodes.Add(newNode);
			}
			else
				// if documentation, add a tree node
				if (doc != null)
			{
				newNode=new TreeNode("--documentation--");
				newNode.Tag=doc;
				newNode.ImageIndex=5;
				newNode.SelectedImageIndex=5;
				node.Nodes.Add(newNode);
			}
			else
				// if app info, add a tree node
				if (appInfo != null)
			{
				newNode=new TreeNode("--app info--");
				newNode.Tag=annot;
				newNode.ImageIndex=6;
				newNode.SelectedImageIndex=6;
				node.Nodes.Add(newNode);
			}
			else
				// if an element, determine whether the element is a simple type or a complex type
				if (element != null)
			{
				XmlSchemaSimpleType st=element.SchemaType as XmlSchemaSimpleType;
				XmlSchemaComplexType ct=element.SchemaType as XmlSchemaComplexType;

				if (st != null)
				{
					// this is a simple type element.  Recurse.
					TreeNode node2=DecodeSchema2(st, newNode);
					node2.Text=element.Name;
				}
				else if (ct != null)
				{
					// this is a complex type element.  Recurse.
					TreeNode node2=DecodeSchema2(ct, newNode);
					node2.Text=element.Name;
				}
				else
				{
					// This is a plain ol' fashioned element.
					newNode=new TreeNode(element.QualifiedName.Name);
					newNode.Tag=element;
					newNode.ImageIndex=1;
					newNode.SelectedImageIndex=1;
					node.Nodes.Add(newNode);
				}
			}
			else
				// if a simple type, then add a tree node and recurse facets
				if (simpleType != null)
			{
				newNode=new TreeNode(simpleType.QualifiedName.Name);
				newNode.Tag=simpleType;
				newNode.ImageIndex=2;
				newNode.SelectedImageIndex=2;
				node.Nodes.Add(newNode);
				XmlSchemaSimpleTypeRestriction rest=simpleType.Content as XmlSchemaSimpleTypeRestriction;
				if (rest != null)
				{
					foreach (XmlSchemaFacet schemaObject in rest.Facets)
					{
						DecodeSchema2(schemaObject, newNode);
					}
				}
			}
			else
				// if a complex type, add a tree node and recurse its sequence
				if (complexType != null)
			{
				newNode=new TreeNode(complexType.Name);
				newNode.Tag=complexType;
				newNode.ImageIndex=3;
				newNode.SelectedImageIndex=3;
				node.Nodes.Add(newNode);

				XmlSchemaSequence seq=complexType.Particle as XmlSchemaSequence;
				if (seq != null)
				{
					foreach (XmlSchemaObject schemaObject in seq.Items)
					{
						DecodeSchema2(schemaObject, newNode);
					}
				}
			}

			// now recurse any object collection of the type.
			foreach (PropertyInfo property in obj.GetType().GetProperties())
			{
				if (property.PropertyType.FullName == "System.Xml.Schema.XmlSchemaObjectCollection")
				{
					XmlSchemaObjectCollection childObjectCollection=(XmlSchemaObjectCollection) property.GetValue(obj, null);
					foreach (XmlSchemaObject schemaObject in childObjectCollection) 
					{
						DecodeSchema2(schemaObject, newNode);
					}
				}
			}
			return newNode;
		}
		#endregion
	}
}

